package com.gt.quality.system.controller;


import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import cn.idev.excel.FastExcel;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gt.quality.config.aspectj.annotation.Log;
import com.gt.quality.config.aspectj.enums.BusinessType;
import com.gt.quality.base.BaseCommonController;
import com.gt.quality.base.BaseCommonService;
import com.gt.quality.base.UserSexEnum;
import com.gt.quality.config.utils.LoginHelper;
import com.gt.quality.config.utils.LoginUser;
import com.gt.quality.config.utils.TenantConstants;
import com.gt.quality.system.entity.SysFileInfo;
import com.gt.quality.system.entity.SysUser;
import com.gt.quality.system.entity.dto.SysUserDTO;
import com.gt.quality.system.entity.vo.QueryWhereUser;
import com.gt.quality.system.entity.vo.SaveUserInfo;
import com.gt.quality.base.pojo.BaseLimitResponse;
import com.gt.quality.base.pojo.Resp;
import com.gt.quality.system.service.SysUserService;
import com.gt.quality.system.service.excel.user.ExcelExportUserInfo;
import com.gt.quality.utils.PinYinUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 用户信息表(SysUser)表控制层
 *
 * @author makejava
 * @since 2026-11-25 16:30:08
 */
@RestController
@RequestMapping("sysUser")
@Tag(name = "用户管理")
@Slf4j
public class SysUserController extends BaseCommonController<SysUser> {

    private SysUserService sysUserService;

    public static final String XLSX = ".xlsx";

    /**
     * 服务对象
     */
    @Autowired
    public void setSysUserService(SysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }


    @PostMapping(value = "/api/upload")
    @Operation(summary = "Excel用户导入")
    public Resp<Object> uploadFile(@RequestParam("file") MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename) || !originalFilename.endsWith(XLSX)) {
            return Resp.error("Excel格式不对,请选择" + XLSX + "文件上");
        }
        // 实现文件导入到表 SysUser
        SysFileInfo fileInfo = sysUserService.uploadFile(file);
        return Resp.ok(fileInfo);
    }

    /**
     * 文件下载并且失败的时候返回json（默认失败了会返回一个有部分数据的Excel）
     *
     * @since 2.1.1
     */
    @GetMapping("/api/modelDown")
    @Operation(summary = "Excel用户导入模板下载")
    @SaIgnore
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        try {
            List<ExcelExportUserInfo> data = new ArrayList<>();
            data.add(ExcelExportUserInfo.buildTemplateData());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("用户导入模板", StandardCharsets.UTF_8).replace("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + XLSX);
            // 这里需要设置不关闭流
            FastExcel.write(response.getOutputStream(), ExcelExportUserInfo.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                    .doWrite(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Resp<Object> error = Resp.error("下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(error));
        }
    }

    @Override
    public BaseCommonService<SysUser> getThisService() {
        return sysUserService;
    }


    /**
     * Description:  系统用户管理
     *
     * @author: makeJava
     * @date: 2026-12-22 19:32:14
     */
    @PostMapping("/queryForPage")
    @Operation(summary = "分页查询请求")
    @SaCheckPermission("system:user:list")
    public BaseLimitResponse<SysUserDTO> queryLimitBySuper(@RequestBody QueryWhereUser limitRequest) {
        // 分页查询
        IPage<SysUserDTO> page = this.sysUserService.queryLimit(limitRequest);
        List<SysUserDTO> records = page.getRecords();
        // 封装返回结果集
        return BaseLimitResponse.getInstance(records, page.getTotal(), page.getPages(), limitRequest.getPageIndex(), limitRequest.getPageSize());
    }


    /**
     * 新增数据
     *
     * @param userInfo 实体对象
     * @return 新增结果
     */
    @PostMapping("/insertBySuper")
    @SaCheckPermission("system:user:save")
    @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
    @Operation(summary = "新增数据")
    @Log(title = "超级管理员新增用户", businessType = BusinessType.INSERT)
    public Resp<String> insertBySuper(@RequestBody SaveUserInfo userInfo, HttpServletRequest request) {
        String deptId = userInfo.getDeptId();
        String[] split = deptId.split("/");
        if (split.length > 1) {
            deptId = split[split.length - 1];
        }
        userInfo.setDeptId("");
        SysUser sysUser = JSONUtil.toBean(JSONUtil.parseObj(userInfo), SysUser.class);
        String nickName = userInfo.getNickName();
        // 中文称呼--转化为拼音为账号
        String normalized = PinYinUtil.toPinyin(nickName);
        if (normalized.length() > 30) {
            normalized = normalized.substring(0, 30);
        }
        // 生成手机号
        sysUser.setUserName(normalized);
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUserName, normalized);
        queryWrapper.eq(StringUtils.isNoneBlank(userInfo.getPhoneNumber()), SysUser::getPhoneNumber, userInfo.getPhoneNumber());
        List<SysUser> userList = sysUserService.list(queryWrapper);
        if (CollUtil.isNotEmpty(userList)) {
            return Resp.error("用户名称或者手机号已经被注册了");
        }
        sysUser.setDeptId(StringUtils.isBlank(deptId) ? 103L : Long.parseLong(deptId));
        sysUser.setTenantId(StringUtils.isBlank(sysUser.getTenantId()) ? TenantConstants.DEFAULT_TENANT_ID : sysUser.getTenantId());
        sysUser.setUserType(StringUtils.isBlank(sysUser.getUserType()) ? TenantConstants.USER_TYPE : sysUser.getUserType());
        sysUser.setSex(StringUtils.isBlank(sysUser.getSex()) ? UserSexEnum.Default.getCode().toString() : sysUser.getSex());
        sysUser.setStatus(TenantConstants.NORMAL);
        // 设置默认头像
        sysUser.setAvatar(TenantConstants.DEFAULT_IMAGE_AVATAR);
        sysUser.setLoginIp(request.getRemoteHost());
        String password = SecureUtil.md5(sysUser.getPassword());
        sysUser.setPassword(password);
        LoginUser loginUser = LoginHelper.getLoginUser();
        assert loginUser != null;
        sysUser.setCreateBy(loginUser.getUserId());
        sysUser.setCreateDept(loginUser.getDeptId());
        sysUser.setUpdateBy(loginUser.getUserId());
        boolean save = this.sysUserService.save(sysUser);
        String executeMsg = "id 是：" + sysUser.getUserId();
        return save ? Resp.ok(executeMsg) : Resp.error(executeMsg);
    }


    /**
     * 修改数据
     *
     * @param sysUserDTO 实体对象
     * @return 修改结果
     */
    @PutMapping("/updateUser")
    @Operation(summary = "修改数据")
    @SaCheckPermission("system:user:update")
    public Resp<String> updateUser(@RequestBody SysUserDTO sysUserDTO) {
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserDTO, sysUser);
        Long userId = LoginHelper.getUserId();
        // 是否是修改了密码
        if (StringUtils.isNotBlank(sysUser.getPassword())) {
            String password = SecureUtil.md5(sysUser.getPassword());
            sysUser.setPassword(password);
        }
        sysUser.setUpdateTime(LocalDateTime.now());
        sysUser.setUpdateBy(userId);
        sysUser.setCreateTime(sysUser.getCreateTime() == null ? LocalDateTime.now() : sysUser.getCreateTime());
        sysUser.setCreateDept(sysUser.getCreateDept() != null ? sysUser.getCreateDept() : LoginHelper.getDeptId());
        sysUser.setCreateBy(sysUser.getCreateBy() != null ? sysUser.getCreateBy() : userId);
        // 确保是否是本人或者超级管理
        if (Objects.equals(sysUser.getUserId(), userId)
            || Objects.equals(userId, TenantConstants.SUPER_ADMIN_ID)) {
            sysUser.setStatus(sysUserDTO.isStatus() ? "1" : "0");
            sysUser.setSex(StringUtils.isBlank(sysUser.getSex()) ? UserSexEnum.Default.getCode().toString() : sysUser.getSex());
            this.sysUserService.updateById(sysUser);
            return Resp.ok("id->" + sysUser.getUserId());
        }
        return Resp.error("非法操作,您不具备权限");
    }

    /**
     * 删除数据
     *
     * @param idList 主键结合
     * @return 删除结果
     */
    @DeleteMapping("/dels")
    @SaCheckPermission("system:user:del")
    @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
    @Operation(summary = "删除数据-idList 主键结合")
    @Override
    public Resp<String> delete(@RequestParam("idList") List<Long> idList) {
        boolean delNumber = this.sysUserService.removeByIds(idList);
        String executeMsg = "idList 是：" + idList;
        return delNumber ? Resp.ok(executeMsg) : Resp.error(executeMsg);
    }

    @Override
    protected boolean isSuperExcel() {
        return false;
    }
}
